package com.mingqijia.gassafety.webserver.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gap.basic.exception.BizException;
import com.gap.basic.utils.CollectionUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mingqijia.gassafety.db.entity.FieldTemplate;
import com.mingqijia.gassafety.db.entity.FileExport;
import com.mingqijia.gassafety.db.mapper.FileExportMapper;
import com.mingqijia.gassafety.db.mapper.OrganizationMapper;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.constant.DataExporterConst;
import com.mingqijia.gassafety.shared.constant.ExportCodeEnum;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import com.mingqijia.gassafety.shared.utils.commonUtils.DateUtils;
import com.mingqijia.gassafety.shared.utils.commonUtils.ExportUtils;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageUtil;
import com.mingqijia.gassafety.webserver.request.FileExportCreateRequest;
import com.mingqijia.gassafety.webserver.request.FileExportQueryRequest;
import com.mingqijia.gassafety.webserver.service.FileExportService;
import com.mingqijia.gassafety.webserver.response.ExportResultResponse;
import com.mingqijia.gassafety.webserver.response.FileExportResponse;
import com.mingqijia.gassafety.webserver.service.OrganizationService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 * 文件导出
 *
 * @author wanghai
 * @since 2022-02-21
 */

@Slf4j
@Service
public class FileExportServiceImpl extends ServiceImpl<FileExportMapper,FileExport> implements FileExportService {
    @Autowired
    ExportUtils exportUtils;
    @Value( "${gassafety.job.api.url}" )
    private String gassafeyJobUrl;
    @Autowired
    FileExportMapper fileExportMapper;
    @Autowired
    FileExportService fileExportService;
    @Autowired
    OrganizationMapper organizationMapper;

    @Override
    public void create(FileExportCreateRequest params, FieldTemplate template ){
        ExportCodeEnum exportCodeEnum = ExportCodeEnum.getExportCode(params.getExportCode(), template.getTemplateType());
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("token : {}",request.getHeader("Authorization"));
        String name = String.valueOf(System.currentTimeMillis());
        String creator = ApplicationUtils.getWorkingUser().getUsername();
        String spid = ApplicationUtils.getWorkingSpId();
        // 生成 customized_table_header
        Map<String, Object> customizedHeader ;
        //是否有子组织
        List<String> childList = organizationMapper.getChildList(spid);
        log.info("create-fileExport-template:{}",template);
        log.info("create-fileExport-exportCodeEnum:{}",exportCodeEnum);
        log.info("create-getFields:{},getTitles:{}",JSONObject.toJSONString(exportCodeEnum.getFields()),JSONObject.toJSONString(exportCodeEnum.getTitles()));
        if (!CollectionUtils.isEmpty(childList) && isSpecialize(params.getExportCode())){
            customizedHeader = exportUtils.getCustomizedTableHeaderWithOrganization(
                    null,exportCodeEnum.getFields(),exportCodeEnum.getTitles());
        }else {
            customizedHeader = exportUtils.getCustomizedTableHeader(
                    null,exportCodeEnum.getFields(),exportCodeEnum.getTitles());
        }

        //数据源请求地址
        String url = gassafeyJobUrl + exportCodeEnum.getUrl();
        log.info( "导出数据源url:{}",url );
        //查询这是今日第多少次导出
        Date date = new Date();
        QueryWrapper<FileExport> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq( FileExport::getExportCode,params.getExportCode() )
                .eq( FileExport::getSpId,spid )
                .eq( FileExport::getIsDeleted,Constants.IS_DELETED_FALSE )
                .between( FileExport::getCreatedAt,DateUtil.beginOfDay(date),DateUtil.endOfDay(date));
        queryWrapper.select( "count(*) as sum" );
        Map<String, Object> map = this.getMap( queryWrapper );
        String s = map.get( "sum" ).toString();
        int sum =Integer.parseInt( s )+1;
        String fileName = exportCodeEnum.getName()+"_"+DateUtil.format(date,"yyyy-MM-dd"  ) +"_("+sum+")";
         //queryHeader,  token传递
        Map<String, Object> queryHeader = getQueryHeader(request);
        //添加spID为查询入参
        String queryBody = params.getQueryBody().toString();
        if (params.getQueryBody()== null){
            queryBody =  JSONUtil.createObj().set("spId", spid ).set("templateType",template.getTemplateType()).toString();
        }else if (params.getQueryBody().get("spId") == null){
            queryBody = params.getQueryBody().set( "spId", spid ).set("templateType",template.getTemplateType()).toString();
        }
        log.info( "queryBody: {}", queryBody );
        //创建任务
        JSONObject jSONObject = exportUtils.getCreateTaskParams(params.getExportCode(),name,creator,
                url,queryHeader,queryBody,customizedHeader,
                fileName,1,null,null);
        Long taskId = exportUtils.createTask(jSONObject);

        if (taskId != null) {
            //insert
            FileExport record = new FileExport();
            record.setExportCode(params.getExportCode());
            record.setExportName(name);
            record.setFileName(fileName);
            record.setTaskId(taskId);
            record.setQueryUrl(exportCodeEnum.getUrl());
            //String jsonParam = new ObjectMapper().writeValueAsString(queryHeader);
            record.setQueryHeader(null);
            record.setQueryBody(queryBody);
            record.setExportCreator(creator);
            record.setCreatorName(ApplicationUtils.getWorkingUser().getName());
            record.setSpId(spid);
            int count = fileExportMapper.insert(record);
            log.info("创建导出任务结果:{},对象:{}",count,record.toString());
        }else {
            throw new BizException("创建导出任务失败.");
        }
    }

    private boolean isSpecialize(String exportCode) {
       if (ExportCodeEnum.EXPORT_1_1.getCode().equals(exportCode) || ExportCodeEnum.EXPORT_1_2.getCode().equals(exportCode)
               || ExportCodeEnum.EXPORT_5.getCode().equals(exportCode)|| ExportCodeEnum.EXPORT_6.getCode().equals(exportCode)
               || ExportCodeEnum.EXPORT_7.getCode().equals(exportCode) || ExportCodeEnum.EXPORT_14.getCode().equals(exportCode)
       || ExportCodeEnum.EXPORT_15.getCode().equals(exportCode) || ExportCodeEnum.EXPORT_16_1.getCode().equals(exportCode)
       || ExportCodeEnum.EXPORT_16_2.getCode().equals(exportCode)){
           return false;
       }
       return true;
    }

    @Override
    public PageUtil<FileExportResponse> getPdfList(FileExportQueryRequest params) {
        String spId = ApplicationUtils.getWorkingSpId();
        Page<FileExport> page = PageHelper.startPage(params.getPage(), params.getPageSize());
        List<FileExportResponse> resultList = new ArrayList<>();
        QueryWrapper<FileExport> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq( FileExport::getExportCode,params.getExportCode() )
                .like( StringUtils.isNotEmpty(params.getFileName()), FileExport::getFileName,params.getFileName() )
                .eq( params.getExportStatus() != null, FileExport::getExportStatus,params.getExportStatus() )
                .eq( FileExport::getIsDeleted, Constants.IS_DELETED_FALSE );
        // 数据隔离
        if (spId != null) {
            queryWrapper.lambda().in( FileExport::getSpId, spId );
        }
        queryWrapper.orderByDesc( "created_at" );
        List<FileExport> exportList =  fileExportMapper.selectList(queryWrapper);

        for (FileExport fileExport : exportList) {
            FileExportResponse vo = new FileExportResponse();
            BeanUtils.copyProperties(fileExport,vo);
            switch (fileExport.getExportStatus()){
                case "1": vo.setExportStatus("进行中"); break;
                case "2": vo.setExportStatus("成功");break;
                case "3": vo.setExportStatus("失败");break;
                default:
            }

            String createTime = DateUtils.format( fileExport.getCreatedAt(), "yyyy-MM-dd HH:mm:ss" );
            vo.setCreateTime(  createTime );
            resultList.add(vo);
        }
        //设置分页参数
        PageUtil<FileExportResponse> pager = new PageUtil<>();
        pager.setPage(page.getPageNum());
        pager.setPageSize(page.getPageSize());
        pager.setTotal(page.getTotal());
        pager.setList(resultList);
        return pager;
    }

    @Override
    public PageUtil<FileExportResponse> getList(FileExportQueryRequest params) {
        String spId = ApplicationUtils.getWorkingSpId();
        // 各个组织账号只能看自己归属下的数据
        //平台管理员可以查看所有数据  orgid =null
        //正在处理中任务
        List<FileExportResponse> resultList = new ArrayList<>();
        QueryWrapper<FileExport> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq( FileExport::getExportCode,params.getExportCode() )
                        .eq( FileExport::getExportStatus,  DataExporterConst.STATUS_ING )
                        .eq( FileExport::getIsDeleted, Constants.IS_DELETED_FALSE );
        List<FileExport> list =  fileExportMapper.selectList(wrapper);
        //处理中的任务, 查询处理进度并更新数据库
        for (FileExport fileExport : list) {
            queryFileExport(fileExport.getExportCode(),fileExport.getExportName(),fileExport.getTaskId());
        }
        Page<FileExport> page = PageHelper.startPage(params.getPage(), params.getPageSize());
        QueryWrapper<FileExport> queryWrapper = new QueryWrapper<>();
        // 查询指定导出表的结果
        queryWrapper.lambda().eq( FileExport::getExportCode,params.getExportCode() )
                            .eq( FileExport::getIsDeleted,Constants.IS_DELETED_FALSE );
        // 数据隔离
        if (spId != null) {
            queryWrapper.lambda().in( FileExport::getSpId, spId );
        }
        queryWrapper.orderByDesc( "created_at" );
        List<FileExport> exportList = fileExportMapper.selectList( queryWrapper );
        for (FileExport fileExport : exportList) {
            FileExportResponse vo = new FileExportResponse();
            BeanUtils.copyProperties(fileExport,vo);
            switch (fileExport.getExportStatus()){
                case "1": vo.setExportStatus("进行中"); break;
                case "2": vo.setExportStatus("成功");break;
                case "3": vo.setExportStatus("失败");break;
                default:
            }

            String createTime = DateUtils.format( fileExport.getCreatedAt(), "yyyy-MM-dd HH:mm:ss" );
            vo.setCreateTime(  createTime );
            resultList.add(vo);
        }
        //设置分页参数
        PageUtil<FileExportResponse> pager = new PageUtil<>();
        pager.setPage(page.getPageNum());
        pager.setPageSize(page.getPageSize());
        pager.setTotal(page.getTotal());
        pager.setList(resultList);
        return pager;
    }


    private void queryFileExport(String exportCode,String name,Long taskId) {
        //封装查询任务参数
        JSONObject jsonObject = exportUtils.getSearchTaskParams(exportCode,name,null,
                null,null,null,null);
        //查询任务, 并将结果转换为VO
        JSONObject object = exportUtils.searchTask( jsonObject );
        List<ExportResultResponse> resultList = new ArrayList<>();
        JSONArray array = object.getJSONArray("list") == null ?
                new JSONArray() : object.getJSONArray("list");
        if (!CollectionUtil.isEmpty(array)) {
            array.forEach(o -> {
                JSONObject json = JSONObject.parseObject(o+"");
                ExportResultResponse exportResult = JSON.toJavaObject(json, ExportResultResponse.class);
                resultList.add(exportResult);

            });
        }
        for (ExportResultResponse exportResult : resultList) {
            if (exportResult.getId().equals(taskId)) {
                FileExport record = new FileExport();
                record.setTaskId(taskId);
                //导出成功
                if (exportResult.getStatus() == 2) {
                    record.setExportStatus(DataExporterConst.STATUS_SUCCESS);
                    record.setExportUrl(exportResult.getResource());
                } else if (exportResult.getStatus() == 3) {
                    //导出失败
                    record.setExportStatus(DataExporterConst.STATUS_FAIL);
                    int length = exportResult.getErrorDesc().length() > 499 ? 499 : exportResult.getErrorDesc().length();
                    record.setExportDesc(exportResult.getErrorDesc().substring(0,length));
                }
                QueryWrapper<FileExport> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq( FileExport::getTaskId,taskId ).eq( FileExport::getIsDeleted,Constants.IS_DELETED_FALSE );
                boolean update = fileExportService.update(record,queryWrapper);
                log.info("更新文件导出表结果:{}",record.toString());
            }
        }
    }


    /**
     * 封装创建任务时的查询用header信息
     * @param request
     * @return
     */
    private Map<String, Object> getQueryHeader(HttpServletRequest request){
        Map<String, Object> headers = new HashMap<>();
        if (request.getHeader("templateType") !=null){
            headers.put("templateType",request.getHeader("templateType"));
        }
        headers.put("x-sp-id",request.getHeader("x-sp-id"));
        headers.put("Authorization",request.getHeader("Authorization"));
        return headers;
    }
}
